package com.duckclouddrive.service.impl;

import com.duckclouddrive.component.RedisComponent;
import com.duckclouddrive.entity.dto.SysSettingsDto;
import com.duckclouddrive.mappers.EmailCodeMapper;
import com.duckclouddrive.mappers.UserInfoMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.List;
import com.duckclouddrive.entity.config.AppConfig;
import com.duckclouddrive.entity.constants.Constants;
import com.duckclouddrive.entity.enums.PageSize;
import com.duckclouddrive.entity.po.EmailCode;
import com.duckclouddrive.entity.po.UserInfo;
import com.duckclouddrive.entity.query.EmailCodeQuery;
import com.duckclouddrive.entity.query.SimplePage;
import com.duckclouddrive.entity.query.UserInfoQuery;
import com.duckclouddrive.entity.vo.PaginationResultVO;
import com.duckclouddrive.exception.BusinessException;
import com.duckclouddrive.service.EmailCodeService;
import com.duckclouddrive.utils.StringTools;

/**
 * 邮箱验证码 业务接口实现
 */
@Service("emailCodeService")
public class EmailCodeServiceImpl implements EmailCodeService {

	private static  final Logger logger = LoggerFactory.getLogger(EmailCodeServiceImpl.class);
	@Resource
	private EmailCodeMapper<EmailCode, EmailCodeQuery> emailCodeMapper;

	@Resource
	private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;

	@Resource
	private JavaMailSender javaMailSender;
	@Resource
	private AppConfig appConfig;
	@Resource
	private RedisComponent redisComponent;
	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<EmailCode> findListByParam(EmailCodeQuery param) {
		return this.emailCodeMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(EmailCodeQuery param) {
		return this.emailCodeMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<EmailCode> findListByPage(EmailCodeQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<EmailCode> list = this.findListByParam(param);
		PaginationResultVO<EmailCode> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(EmailCode bean) {
		return this.emailCodeMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<EmailCode> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.emailCodeMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<EmailCode> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.emailCodeMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 根据EmailAndCode获取对象
	 */
	@Override
	public EmailCode getEmailCodeByEmailAndCode(String email, String code) {
		return this.emailCodeMapper.selectByEmailAndCode(email, code);
	}

	/**
	 * 根据EmailAndCode修改
	 */
	@Override
	public Integer updateEmailCodeByEmailAndCode(EmailCode bean, String email, String code) {
		return this.emailCodeMapper.updateByEmailAndCode(bean, email, code);
	}

	/**
	 * 根据EmailAndCode删除
	 */
	@Override
	public Integer deleteEmailCodeByEmailAndCode(String email, String code) {
		return this.emailCodeMapper.deleteByEmailAndCode(email, code);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void sendEmailCode(String email, Integer type) {
         if(type == Constants.ZERO){
			 UserInfo userInfo = userInfoMapper.selectByEmail(email);
		     if(null != userInfo){
				 throw  new BusinessException("邮箱已经存在");
			 }
		 }
		 String code = StringTools.getRandomNumber(Constants.LENGTH_5);
		 //发送验证码
		 sendEmailCode(email,code);
		 //将之前的验证码值为无效
		 emailCodeMapper.disableEmailCode(email);
		 EmailCode emailCode= new EmailCode();
		 emailCode.setCode(code);
		 emailCode.setEmail(email);
		 emailCode.setStatus(Constants.ZERO);
		 emailCode.setCreateTime(new Date());
		 emailCodeMapper.insert(emailCode);
	}
	/**
	 * 发送邮箱验证码
	 *
	 * @param toEmail 收件人的电子邮件地址
	 * @param code 需要发送的验证码
	 *
	 * 该方法创建并发送一个包含验证码的电子邮件到指定的邮箱地址
	 * 它使用JavaMailSender接口和MimeMessageHelper类来准备和发送邮件
	 * 邮件内容和标题是从系统配置中获取的，验证码是动态生成的
	 * 如果邮件发送过程中出现异常，会记录错误并抛出自定义的业务异常
	 */
	private void sendEmailCode(String toEmail, String code) {
	    try {
	        // 创建一个MimeMessage实例，用于构造复杂的邮件内容
	        MimeMessage message = javaMailSender.createMimeMessage();
	        MimeMessageHelper helper = new MimeMessageHelper(message,true);
	        // 设置邮件的发件人，从应用配置中获取
	        helper.setFrom(appConfig.getSendUserName());
	        // 设置邮件的收件人
	        helper.setTo(toEmail);
	        // 从Redis中获取系统配置信息
	        SysSettingsDto sysSettingsDto = redisComponent.getSysSettingsDto();
	        // 设置邮件的主题
	        helper.setSubject(sysSettingsDto.getRegisterEmailTitle());
	        // 设置邮件的正文，包含验证码
	        helper.setText(String.format(sysSettingsDto.getRegisterEmailContent(), code));
	        // 设置邮件的发送日期
	        helper.setSentDate(new Date());
	        // 发送邮件
	        javaMailSender.send(message);
	    } catch (Exception e) {
	        // 记录邮件发送失败的错误信息
	        logger.error("邮件发送失败",e);
	        // 抛出自定义的业务异常，通知调用者邮件发送失败
	        throw new BusinessException("邮件发送失败");
	    }
	}

	/**
	 * 验证邮箱验证码
	 *
	 * @param email 用户邮箱
	 * @param code 验证码
	 * @throws BusinessException 验证码不正确或已失效时抛出业务异常
	 */
	@Override
	public void checkCode(String email, String code) {
	    // 根据邮箱和验证码查询数据库
	    EmailCode emailCode = this.emailCodeMapper.selectByEmailAndCode(email, code);
	    // 如果查询结果为空，抛出验证码不正确的异常
	    if (null == emailCode) {
	        throw new BusinessException("邮箱验证码不正确");
	    }
	    // 如果验证码状态已使用或超过15分钟有效期，抛出验证码已失效的异常
	    if (emailCode.getStatus() == 1 || System.currentTimeMillis() - emailCode.getCreateTime().getTime() > Constants.LENGTH_15 * 60 * 1000) {
	        throw new BusinessException("邮箱验证码已失效");
	    }
	    // 验证码核对无误后，更新验证码状态为已使用
	    emailCodeMapper.disableEmailCode(email);
	}
}